package com.sxf.jetty;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.ServletContainerInitializer;
import javax.servlet.annotation.HandlesTypes;

import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.annotations.ClassInheritanceHandler;
import org.eclipse.jetty.annotations.ContainerInitializerAnnotationHandler;
import org.eclipse.jetty.annotations.ServletContainerInitializersStarter;
import org.eclipse.jetty.jsp.JettyJspServlet;
import org.eclipse.jetty.plus.annotation.ContainerInitializer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.ConcurrentHashSet;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
import org.springframework.web.SpringServletContainerInitializer;

public class LocalJetty {
	private static int port = 80;
	private static final String WEB_ROOT = "src/main/webapp";
	private static final String WEB_DEFALULT = "src/test/resources/jetty/webdefault.xml";

	public static void main(String[] args) throws Exception {
		System.setProperty("java.net.preferIPv4Stack", "true");
		WebAppContext context = new WebAppContext();

		// 得到hae目录
		File rootDir = new File(System.getProperty("user.dir")).getParentFile();
		rootDir = new File(rootDir, "/wordpressMaven");

		String path = new File(rootDir, WEB_ROOT).getAbsolutePath();
		context.setBaseResource(Resource.newResource(path));
		context.setContextPath("/wp");
		context.setParentLoaderPriority(true);
		context.setConfigurations(new Configuration[] { new Config() });

		// SpringMVC为寻找名为default的Servlet来处理静态资源
		ServletHolder sh = new ServletHolder("default", DefaultServlet.class);
		context.addServlet(sh, "/");

		sh = new ServletHolder("jsp", JettyJspServlet.class);
		context.addServlet(sh, "*.jsp");
		// 指定缺省配置，但好像不起作用?
		context.setDefaultsDescriptor(new File(rootDir, WEB_DEFALULT)
				.getAbsolutePath());

		Server server = new Server(port);

		// Enable parsing of jndi-related parts of web.xml and jetty-env.xml
		org.eclipse.jetty.webapp.Configuration.ClassList classList = org.eclipse.jetty.webapp.Configuration.ClassList
				.setServerDefault(server);
		classList.addAfter("org.eclipse.jetty.webapp.FragmentConfiguration",
				"org.eclipse.jetty.plus.webapp.EnvConfiguration",
				"org.eclipse.jetty.plus.webapp.PlusConfiguration");
		classList.addBefore(
				"org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
				"org.eclipse.jetty.annotations.AnnotationConfiguration");
		// Create a WebAppContext

		server.setHandler(context);
		WebSocketServerContainerInitializer.configureContext(context);
		server.setStopAtShutdown(true);
		server.start();
		server.join();
	}

	public static class Config extends AnnotationConfiguration {
		public void createServletContainerInitializerAnnotationHandlers(
				WebAppContext context,
				java.util.List<javax.servlet.ServletContainerInitializer> scis)
				throws Exception {
			if (scis == null || scis.isEmpty())
				return; // nothing to do
			List<ContainerInitializer> initializers = new ArrayList<ContainerInitializer>();
			context.setAttribute(CONTAINER_INITIALIZERS, initializers);

			for (ServletContainerInitializer service : scis) {
				HandlesTypes annotation = service.getClass().getAnnotation(
						HandlesTypes.class);
				ContainerInitializer initializer = null;
				if (annotation != null) {
					// There is a HandlesTypes annotation on the on the
					// ServletContainerInitializer
					Class<?>[] classes = annotation.value();
					if (classes != null) {
						initializer = new ContainerInitializer(service, classes);
						if (service instanceof SpringServletContainerInitializer) {
							// classes = new Class[] {
							// DispatcherServletInitializer.class };
							// initializer = new ContainerInitializer(service,
							// classes);
							initializer
									.addApplicableTypeName("com.sxf.web.DispatcherServletInitializer");
						}
						// If we haven't already done so, we need to
						// register a handler that will
						// process the whole class hierarchy to satisfy the
						// ServletContainerInitializer
						if (context.getAttribute(CLASS_INHERITANCE_MAP) == null) {
							// MultiMap<String> map = new MultiMap<>();
							ConcurrentHashMap<String, ConcurrentHashSet<String>> map = new ClassInheritanceMap();
							context.setAttribute(CLASS_INHERITANCE_MAP, map);
							_classInheritanceHandler = new ClassInheritanceHandler(
									map);
						}
						for (Class<?> c : classes) {
							// The value of one of the HandlesTypes classes
							// is actually an Annotation itself so
							// register a handler for it
							if (c.isAnnotation()) {
								_containerInitializerAnnotationHandlers
										.add(new ContainerInitializerAnnotationHandler(
												initializer, c));
							}
						}
					} else {
						initializer = new ContainerInitializer(service, null);
					}
				} else {
					initializer = new ContainerInitializer(service, null);
				}
				initializers.add(initializer);
			}
			// add a bean to the context which will call the
			// servletcontainerinitializers when appropriate
			ServletContainerInitializersStarter starter = (ServletContainerInitializersStarter) context
					.getAttribute(CONTAINER_INITIALIZER_STARTER);
			if (starter != null)
				throw new IllegalStateException(
						"ServletContainerInitializersStarter already exists");
			starter = new ServletContainerInitializersStarter(context);
			context.setAttribute(CONTAINER_INITIALIZER_STARTER, starter);
			context.addBean(starter, true);
		};
	}

}
